﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using CoursePack;
using ScheduleGrid;

using Heap;

namespace Scheduler
{
    [Serializable]
    public class Schedule
    {
        #region Data
        private const int MAX_COURSES_ALLOWED = 5;
        private List<Course> m_Courses;
        private List<Appointment> m_AppCourses;
        private List<Color> m_Colors;
        private DateTime m_ScheduleViewerTime;
        private Student m_Student;
        private ScheduleManager m_Parent;
        #endregion

        public Schedule(DateTime _Time, Student _Student,ScheduleManager _Parent)
        {
            this.m_Courses = new List<Course>();
            this.m_AppCourses = new List<Appointment>();

       
            m_Colors = new List<Color>();
            m_Colors.Add(Color.Blue);
            m_Colors.Add(Color.Yellow);
            m_Colors.Add(Color.Tomato);
            m_Colors.Add(Color.Black);
            m_Colors.Add(Color.Violet);

            this.m_ScheduleViewerTime = _Time;
            this.m_Student = _Student;
            this.m_Parent = _Parent;
        }

        public bool AddCourse(Course _Course)
        {
            if ((this.m_Courses.Count < MAX_COURSES_ALLOWED) && (this.m_Courses.Find(o => o == _Course) == null))
            {
                this.m_Courses.Add(_Course);

                return true;
            }
            else
                return false;
        }

        public bool RemoveAppointment(Appointment _App)
        {
            if (_App != null)
            {
                // If the appointment type is a course
                if (_App.AppointmentType == AppType.Course)
                {
                    this.RemoveCourse(((AppointmentCourse)_App).Course);
                }
                else
                {

                    this.m_Parent.RemoveTimeConstraint(((AppointmentTimeConstraint)_App).TimeConstraint);
                    this.m_AppCourses.Remove(_App);
                }

                return true;
            }
            else
                return false;

        }

        public bool RemoveCourse(Course _Course)
        {
            List<Appointment> appsToRemove = new List<Appointment>();
            Course courseToRemove = null;

            foreach (Appointment app in this.m_AppCourses)
            {
                if (app.AppointmentType == AppType.Course)
                {
                    if (((AppointmentCourse)app).Course == _Course)
                    {
                        appsToRemove.Add(app);
                    }
                }
            }


            // Just to make sure of appointment has been found in the schedule
            // Then we need to remvoe the course of the appointment
            if (appsToRemove.Count > 0)
                courseToRemove = _Course;


            foreach (Appointment app in appsToRemove)
                this.m_AppCourses.Remove(app);

           
            return this.m_Courses.Remove(_Course);

        }

        public bool IsCourseIn(Course _Course)
        {
            return (this.m_Courses.Find(o => o == _Course) != null) ? true : false;
        }

        public override bool Equals(object obj)
        {
            bool flag = true;
            Schedule schedule = (Schedule) obj;

            foreach (Course c in this.Courses)
            {
                if (schedule.Courses.Contains(c) != true)
                    flag = false;
            }

            foreach (Constraint cons in this.m_Parent.ConstraintManager.Constraints)
            {
                if (this.m_Parent.ConstraintManager.Constraints.Contains(cons) != true)
                    flag = false;
            }

            
            return flag;
        }

        #region Accessors
        public List<Appointment> Appointments
        {
            get { return this.m_AppCourses; }
        }

        public List<Course> Courses
        {
            get { return this.m_Courses; }
        }

        public bool IsFull
        {
            get { return (this.m_Courses.Count == MAX_COURSES_ALLOWED) ? true : false; }
        }

        public int NumberOfConflicts()
        {
            int courseConflicts = 0;

            for(int i = 0; i < this.m_Courses.Count;i++)
                for(int j = i;j < this.m_Courses.Count;j++)
                {
                    if (j + 1 < this.m_Courses.Count)
                    {
                        Course courseI = this.m_Courses[i];
                        Course courseJ = this.m_Courses[j + 1];

                        courseConflicts += courseI.CourseConficts(courseJ);
                    }
                    else
                        break;

                }

            return courseConflicts;
        }
        #endregion
    }
}
